package org.vectrics.project.task;

import java.util.Iterator;
import java.util.List;

import org.apache.log4j.Logger;
import org.hibernate.Query;
import org.hibernate.Session;
import org.vectrics.DataException;
import org.vectrics.SystemException;
import org.vectrics.hibernate.Filter;
import org.vectrics.hibernate.Selector;
import org.vectrics.hibernate.ThreadProperties;
import org.vectrics.provider.CoreServiceLocator;


/**
 * @author mmoore
 */
public class ProjectService {
	private transient Logger log = Logger.getLogger(this.getClass());
	
	private Filter createFilterForTaskCriteria(TaskCriteria taskCriteria) {
		Filter filter = new Filter();
		filter.addFrom("Task", "task");
		
		if (taskCriteria.getCompany() != null) {
			filter.addParameterCondition("task.company.id", "=", taskCriteria.getCompany().getId());
		}
		
		if (taskCriteria.getStatusTypeCodes().size() > 0) {
			filter.addFrom("TaskStatus", "status");
			Selector allStatusSelector = filter.getSelector().addChildSelector(Selector.CONJUNTION_OR);
			Iterator iter = taskCriteria.getStatusTypeCodes().iterator();
			while (iter.hasNext()) {
				String statusTypeCode = (String)iter.next();
				Selector statusSelector = allStatusSelector.addChildSelector(Selector.CONJUNTION_AND); 
				statusSelector.addParameterCondition("status.taskStatusType.code", "=", statusTypeCode);
				statusSelector.addCondition("status.dateEnd is null");
				statusSelector.addCondition("status.task.id = task.id");
			}
		}
		
		if (taskCriteria.getPerson() != null) {
			filter.addFrom("TaskResource", "resource");
			filter.addCondition("resource.task.id = task.id");
			filter.addParameterCondition("resource.person.id", "=", taskCriteria.getPerson().getId());
		}
		
		return(filter);
	}
	
	public int findTaskCount(TaskCriteria taskCriteria) {
		int count = 0;
		Session session = ThreadProperties.getSession();
		
		Filter filter = this.createFilterForTaskCriteria(taskCriteria);
		filter.addSelectField("count(distinct task.id)");

		log.info("findTaskCount() Statement:" + filter.getStatement());
		Query query = filter.createQuery(session);
		Iterator results = query.iterate();						
		
		if (results == null) {
			throw new DataException("Method does not define logic for criteria");
		} else {
			while ( results.hasNext() ) {
				Object row = (Object)results.next();
				Long countInteger = (Long)row;
				count = countInteger.intValue();
			}
		}
		return(count);
	}
	
	public List findTasks(TaskCriteria taskCriteria, int startIndex, int endIndex) {
        List tasks = null;
        Filter filter = this.createFilterForTaskCriteria(taskCriteria);
        filter.addSelectField("task");
        filter.addOrderBy("task.dueDate");

		log.info("findTasks() Statement:" + filter.getStatement());
		Query query = filter.createQuery(ThreadProperties.getSession());
		if ((endIndex >= 0) && (startIndex >= 0)) {
			query.setMaxResults(1 + endIndex - startIndex);
			query.setFirstResult(startIndex);
		}
		tasks = query.list();
        
        return(tasks);
    }
    
    public void updateTask(Task task) {
    	if (CoreServiceLocator.getConfiguration().getAllowTasks()) {
	    	ThreadProperties.getSession().saveOrUpdate(task);
	    	if (task.getCurrentStatus() == null)
	    		throw new SystemException("Status saved without a status");
    	} else {
    		log.debug("Task will not be saved because task module is not enabled");
    	}
    }
    
    
    public Task findTask(Long id) {
    	Task task = (Task)ThreadProperties.getSession().load(Task.class, id);
    	return(task);
    }
    
    public TaskCategory findTaskCategory(String code) {
    	TaskCategory taskCategory = 
    		(TaskCategory)ThreadProperties.getSession().load(TaskCategory.class, code);
    	return(taskCategory);
    }
    
	public List findTaskChildren(Task parent) {
		Filter filter = new Filter();
		filter.addSelectField("task");
		filter.addFrom("Task",  "task");
		if (parent != null) {
			filter.addParameterCondition("task.parent.id", "=", parent.getId());
		} else {
			filter.addCondition("task.parent is null");
		}
		
		Session session = ThreadProperties.getSession();
		Query query = filter.createQuery(session);

		return query.list();
	}

	
	public TaskStatusType findTaskStatusType(String taskStatusTypeCode) {
    	TaskStatusType taskStatusType = (TaskStatusType)ThreadProperties.getSession().load(TaskStatusType.class, taskStatusTypeCode);
    	return(taskStatusType);
	}
}
